package com.glsc.ngateway.opmanage.service.deposit;

import cn.hutool.core.collection.CollectionUtil;
import com.glsc.ngateway.common.api.common.utils.PageUtil;
import com.glsc.ngateway.common.base.domain.mysql.opmanagemain.deposit.DepositoryBank;
import com.glsc.ngateway.common.base.domain.mysql.opmanagemain.deposit.DepositoryDayStartData;
import com.glsc.ngateway.common.base.domain.oracle.xinyizj.FsBankBal;
import com.glsc.ngateway.common.base.repo.mysql.opmanagemain.deposit.DepositoryDayStartDataRepository;
import com.glsc.ngateway.opmanage.dto.DepositoryStartDataExcelDto;
import com.glsc.ngateway.opmanage.utils.DateUtils;
import com.glsc.ngateway.opmanage.utils.SpecificationUtil;
import com.glsc.ngateway.opmanage.utils.report.ReportFileConfigEnum;
import com.glsc.ngateway.opmanage.utils.report.ReportFileUtil;
import com.glsc.ngateway.opmanage.utils.report.ReportUploadContext;
import com.google.common.collect.Lists;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class DepositoryDayStartDataService {


    @Resource
    private DepositoryDayStartDataRepository depositoryDayStartDataRepository;

    //查询柜台余额信息
    @Resource
    @Lazy
    private FsInDeposMarginBalService fsInDeposMarginBalService;

    @Resource
    private DepositoryBankService depositoryBankService;

    //查询账号余额信息
    @Resource
    private FsBankBalService fsBankBalService;


    /**
     * 每日如初同步柜台余额-定时任务
     */
    @XxlJob("Depository_synMarginGtAmt")
    public void synMarginGtAmt() {
        List<DepositoryBank> banks = depositoryBankService.listAll();
        if (CollectionUtils.isEmpty(banks)) {
            return;
        }

        for (DepositoryBank bank : banks) {
            if (StringUtils.isEmpty(bank.getAccount())) {
                continue;
            }

            if (bank.getBankName().contains("备付金")) {
                continue;
            }

            DepositoryDayStartData data = findByBankAccToday(bank.getAccount());
            if (Objects.isNull(data)) {
                data = DepositoryDayStartData.builder().bankAcc(bank.getAccount()).bankId(bank.getId())
                        .bankName(bank.getBankName()).effectDate(DateUtils.getNowDateString()).deleted("N")
                        .marginGtAmt(BigDecimal.ZERO).marginTotalAmt(BigDecimal.ZERO).build();
            } else {
                data.setMarginGtAmt(BigDecimal.ZERO);
            }
            //查询柜台余额
            BigDecimal fs = fsInDeposMarginBalService.findMarginBalByBankAcc(bank.getAccount());
            if (Objects.nonNull(fs)) {
                data.setMarginGtAmt(fs);
            }
            depositoryDayStartDataRepository.save(data);
        }

    }

    /**
     * 每日如初同步账户余额-定时任务
     */
    @XxlJob("Depository_synMarginTotalAmt")
    public void synMarginTotalAmt() {
        List<DepositoryBank> banks = depositoryBankService.listAll();
        if (CollectionUtils.isEmpty(banks)) {
            return;
        }

        for (DepositoryBank bank : banks) {
            if (StringUtils.isEmpty(bank.getAccount())) {
                continue;
            }

            if (bank.getBankName().contains("备付金")) {
                continue;
            }

            DepositoryDayStartData data = findByBankAccToday(bank.getAccount());
            if (Objects.isNull(data)) {
                data = DepositoryDayStartData.builder().bankAcc(bank.getAccount()).bankId(bank.getId())
                        .bankName(bank.getBankName()).effectDate(DateUtils.getNowDateString()).deleted("N")
                        .marginGtAmt(BigDecimal.ZERO).marginTotalAmt(BigDecimal.ZERO).build();
            } else {
                data.setMarginTotalAmt(BigDecimal.ZERO);
            }
            //查询账户余额
            FsBankBal fsBankBal = fsBankBalService.findByBankAcc(bank.getAccount());
            if (Objects.nonNull(fsBankBal) && Objects.nonNull(fsBankBal.getAccBal())) {
                data.setMarginTotalAmt(fsBankBal.getAccBal());
            }

            depositoryDayStartDataRepository.save(data);
        }

    }


    /**
     * 分页查找
     *
     * @param pageNo
     * @param pageSize
     * @param param
     * @return
     */
    public Page<DepositoryDayStartData> page(int pageNo, int pageSize, Map<String, Object> param) {
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "createTime";

        pageNo = PageUtil.initPageNo(pageNo);
        pageSize = PageUtil.initPageSize(pageSize);

        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, direction, sort);
        Page<DepositoryDayStartData> page = depositoryDayStartDataRepository.findAll(SpecificationUtil.buildSpecification(param, DepositoryDayStartData.class), pageable);

        return page;
    }

    /**
     * 查询今日所有生效状态的存管银行信息
     *
     * @return
     */
    public List<DepositoryDayStartData> listAllEffectToday() {
        List<DepositoryDayStartData> list = depositoryDayStartDataRepository.findAll(Example.of(DepositoryDayStartData.builder().effectDate(DateUtils.getNowDateString()).deleted("N").build()));
        return list;
    }


    /**
     * 根据id查找
     *
     * @param id
     * @return
     */
    public DepositoryDayStartData findById(Integer id) {
        Optional<DepositoryDayStartData> optional = depositoryDayStartDataRepository.findById(id);
        if (optional.isPresent()) {
            return optional.get();
        }
        return null;
    }

    /**
     * 根据名称查找银行信息
     *
     * @param bankName
     * @return
     */
    public DepositoryDayStartData findByName(String bankName) {
        List<DepositoryDayStartData> list = depositoryDayStartDataRepository.findAll(Example.of(DepositoryDayStartData.builder().bankName(bankName).build()));
        if (CollectionUtil.isNotEmpty(list)) {
            return list.get(0);
        }
        return null;
    }

    /**
     * 根据银行账号查找银行信息
     *
     * @param bankAcc
     * @return
     */
    public DepositoryDayStartData findByBankAccToday(String bankAcc) {
        if (StringUtils.isEmpty(bankAcc)) {
            return null;
        }
        List<DepositoryDayStartData> list = depositoryDayStartDataRepository.findAll(Example.of(DepositoryDayStartData.builder()
                .bankAcc(bankAcc).effectDate(DateUtils.getNowDateString()).build()));
        if (CollectionUtil.isNotEmpty(list)) {
            return list.get(0);
        }
        return null;
    }

    /**
     * 保存
     *
     * @param obj
     * @return
     */
    public DepositoryDayStartData save(DepositoryDayStartData obj) {
        return depositoryDayStartDataRepository.save(obj);
    }

    /**
     * 根据id删除
     *
     * @param id
     */
    public void delete(Integer id) {
        depositoryDayStartDataRepository.deleteById(id);
    }


    /**
     * 批量导入保证金日出数据
     *
     * @param file
     * @return
     * @throws IOException
     */
    @Transactional
    public ReportUploadContext<DepositoryStartDataExcelDto, String> dataImport(MultipartFile file) throws IOException {
        ReportUploadContext<DepositoryStartDataExcelDto, String> context = ReportUploadContext.<DepositoryStartDataExcelDto, String>builder()
                .config(ReportFileConfigEnum.DEPOSITORY_DAY_START_DATA)
                .file(file)
                .build();

        ReportFileUtil.readSingleExcel(context);
        Assert.notEmpty(context.getReadRes(), "上传内容不可为空");

        List<DepositoryDayStartData> addList = Lists.newArrayList();

        List<DepositoryStartDataExcelDto> readResList = context.getReadRes();
        if (CollectionUtils.isEmpty(readResList)) {
            return context;
        }

        List<DepositoryBank> banks = depositoryBankService.listAll();
        Map<String, DepositoryBank> bankMap = banks.stream().collect(Collectors.toMap(DepositoryBank::getBankName, e -> e, (i, j) -> j));

        for (DepositoryStartDataExcelDto dto : readResList) {
            DepositoryDayStartData data = DepositoryDayStartData.builder().effectDate(DateUtils.getNowDateString()).deleted("N").build();
            DepositoryBank depositoryBank = bankMap.get(dto.getBankName());
            if (Objects.nonNull(depositoryBank)) {
                data.setBankAcc(depositoryBank.getAccount());
                data.setBankName(depositoryBank.getBankName());
                data.setBankId(depositoryBank.getId());

                data.setMarginTotalAmt(new BigDecimal(dto.getMarginTotalAmt()));
                data.setBankSecTranBalance(new BigDecimal(dto.getBankSecTranBalance()));
                data.setMarginGtAmt(new BigDecimal(dto.getMarginGtAmt()));


                addList.add(data);
            }
        }

        if (CollectionUtils.isNotEmpty(addList)) {
            //查询所有当日的录入的数据
            List<DepositoryDayStartData> todayEffectData = listAllEffectToday();
            if (CollectionUtils.isNotEmpty(todayEffectData)) {
                Set<String> savedBankNameSet = addList.stream().map(DepositoryDayStartData::getBankName).collect(Collectors.toSet());
                List<Integer> deleteList = Lists.newArrayList();
                if (CollectionUtils.isNotEmpty(savedBankNameSet)) {
                    for (DepositoryDayStartData todayData : todayEffectData) {
                        if (savedBankNameSet.contains(todayData.getBankName())) {
                            deleteList.add(todayData.getId());
                        }
                    }

                    if (CollectionUtils.isNotEmpty(deleteList)) {
                        depositoryDayStartDataRepository.deleteAllById(deleteList);
                    }
                }
            }

            depositoryDayStartDataRepository.saveAll(addList);

        }

        return context;
    }


}
